/**
 * 日志系统
 */

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEngine;

namespace GameBaseFramework.Base
{
    /// <summary>
    /// Log接口
    /// </summary>
    public interface ILogger
    {
        /// <summary>
        /// Log
        /// </summary>
        /// <param name="message"></param>
        public void Log(string message);
        /// <summary>
        /// LogWarning
        /// </summary>
        /// <param name="message"></param>
        public void LogWarning(string message);
        /// <summary>
        /// LogError
        /// </summary>
        /// <param name="message"></param>
        public void LogError(string message);
    }

    /// <summary>
    /// Unity Debug
    /// </summary>
    public class UnityDebugConsole : ILogger
    {
        /// <summary>
        /// 参数
        /// </summary>
        private object[] _args = new[] { "" };
        /// <summary>
        /// UnityEngine.Debug Log反射方法
        /// </summary>
        private MethodInfo _log;
        /// <summary>
        /// UnityEngine.Debug LogWarning反射方法
        /// </summary>
        private MethodInfo _logWarning;
        /// <summary>
        /// UnityEngine.Debug LogError反射方法
        /// </summary>
        private MethodInfo _logError;

        /// <summary>
        /// 构造
        /// </summary>
        public UnityDebugConsole()
        {
            var type = Type.GetType("UnityEngine.Debug, UnityEngine");
            _log = type.GetMethod("Log", new Type[] { typeof(object) });
            _logWarning = type.GetMethod("LogWarning", new Type[] { typeof(object) });
            _logError = type.GetMethod("LogError", new Type[] { typeof(object) });
        }

        /// <summary>
        /// Log
        /// </summary>
        /// <param name="message"></param>
        public void Log(string message)
        {
            _args[0] = message;
            _log.Invoke(null, _args);
        }

        /// <summary>
        /// LogWarning
        /// </summary>
        /// <param name="message"></param>
        public void LogWarning(string message)
        {
            _args[0] = message;
            _logWarning.Invoke(null, _args);
        }

        /// <summary>
        /// LogError
        /// </summary>
        /// <param name="message"></param>
        public void LogError(string message)
        {
            _args[0] = message;
            _logError.Invoke(null, _args);
        }
    }

    /// <summary>
    /// System Debug
    /// </summary>
    public class SystemDebugConsole : ILogger
    {
        /// <summary>
        /// Log
        /// </summary>
        /// <param name="message"></param>
        public void Log(string message)
        {
#if TESTQUIZ
            Console.ForegroundColor = ConsoleColor.Black;
#else
            Console.ForegroundColor = ConsoleColor.White;
#endif
            Console.WriteLine(message);
        }

        /// <summary>
        /// LogWarning
        /// </summary>
        /// <param name="message"></param>
        public void LogWarning(string message)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(message);
        }

        /// <summary>
        /// LogError
        /// </summary>
        /// <param name="message"></param>
        public void LogError(string message)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
        }
    }

    /// <summary>
    /// Debug控制台
    /// UnityEngine.Debug和直接在控制台打印Debug信息二选一
    /// 使用ENABLE_DEBUGTOOL_LOG、ENABLE_DEBUGTOOL_LOG_WARNING和ENABLE_DEBUGTOOL_LOG_ERROR三种全局预编译宏来控制Debug信息
    /// </summary>
    public static class DebugTool
    {
        /// <summary>
        /// 控制日志输入
        /// </summary>
        public static bool EnableLog = true;
        /// <summary>
        /// Console
        /// </summary>
        private static ILogger _console;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="console"></param>
        public static void Init(ILogger console)
        {
            EnableLog = true;
            _console = console;
        }

        /// <summary>
        /// Log
        /// </summary>
        /// <param name="message"></param>
        public static void Log([CallerMemberName] string message = null)
        {
            if (EnableLog)
            {
                _console?.Log(message);
            }
        }

        /// <summary>
        /// Log
        /// </summary>
        /// <param name="message"></param>
        public static void Log(bool message)
        {
            if (EnableLog)
            {
                _console?.Log(message.ToString());
            }
        }

        /// <summary>
        /// Log
        /// </summary>
        /// <param name="message"></param>
        public static void Log<T>(T message) where T: IFormatProvider
        {
            if (EnableLog)
            {
                _console?.Log(message.ToString());
            }
        }


        /// <summary>
        /// 格式化输出
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        public static void LogFormat(string message, params object[] args)
        {
            if (message != null)
            {
                Log(string.Format(message, args));
            }
        }

        /// <summary>
        /// LogWarning
        /// </summary>
        /// <param name="message"></param>
        public static void LogWarning(string message, params object[] args)
        {
            if (EnableLog)
            {
                _console?.LogWarning(string.Format(message, args));
            }
        }

        /// <summary>
        /// 打印错误信息
        /// </summary>
        /// <param name="e"></param>
        internal static void LogException(Exception e)
        {
            _console.LogError(e.Message + "\n" + e.StackTrace);
        }

        /// <summary>
        /// LogError
        /// </summary>
        /// <param name="message"></param>
        public static void LogError(string message, params object[] args)
        {
            if (EnableLog)
            {
                _console?.LogError(string.Format(message, args));
            }
        }

        public static void LogJson(this object self)
        {
            Log(self.ToJson());
        }

    }
}
